﻿// Copyright © Microsoft Corporation.  All Rights Reserved.
// This code released under the terms of the 
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
using System;
using System.Collections.Generic;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Text.RegularExpressions;
using System.Collections;
namespace Microsoft.MCSUK.SPSiteDirectory2010
{
    class ScanJobHelperMethods
    {
        public Hashtable GetSiteBeingScannedProperties(SPWeb siteDirectoryWeb, SPWeb webBeingScanned)
        {
            Hashtable fieldsToUpdate = new Hashtable();
            GlobalMethods globalMethods = new GlobalMethods();
            try
            {
                using (SPSite siteBeingScanned = webBeingScanned.Site)
                {
                    ScanJobSettings scanJobSettings = siteBeingScanned.WebApplication.GetChild<ScanJobSettings>(siteBeingScanned.WebApplication.Id.ToString());
                    ScanJobHelperMethods scanJobHelper = new ScanJobHelperMethods();

                    fieldsToUpdate.Add("Title", webBeingScanned.Title);
                    fieldsToUpdate.Add("SiteID", webBeingScanned.ID.ToString().ToUpper());
                    fieldsToUpdate.Add("SiteDescription", webBeingScanned.Description);
                    fieldsToUpdate.Add("SiteTemplate", scanJobHelper.GetWebTemplateTitle(webBeingScanned));
                    fieldsToUpdate.Add("SiteCreationDate", webBeingScanned.Created.ToLongDateString());
                    fieldsToUpdate.Add("SiteURL", scanJobHelper.CreateURLFieldForSite(webBeingScanned, "SITE", scanJobSettings));
                    fieldsToUpdate.Add("SiteOwners", scanJobHelper.GetSiteOwners(siteDirectoryWeb, siteBeingScanned.WebApplication, webBeingScanned));
                    fieldsToUpdate.Add("SiteMultiLingual", webBeingScanned.IsMultilingual);
                    fieldsToUpdate.Add("SiteAuthor", scanJobHelper.GetUserValueAgainstSiteDirectory(siteDirectoryWeb, webBeingScanned.Author));
                    fieldsToUpdate.Add("SiteLanguage", scanJobHelper.GetLanguageNameFromLCID(webBeingScanned.Language));
                    fieldsToUpdate.Add("SiteSecondaryContact", scanJobHelper.GetUserValueAgainstSiteDirectory(siteDirectoryWeb, siteBeingScanned.SecondaryContact));
                    fieldsToUpdate.Add("SiteStorage", scanJobHelper.ConvertBytesToMegabytes(webBeingScanned.Site.Usage.Storage));
                    fieldsToUpdate.Add("SiteHits", siteBeingScanned.Usage.Hits);
                    fieldsToUpdate.Add("SiteQuotaUsed", scanJobHelper.GetPercentageOfQuotaUsed(siteBeingScanned));
                    if (!webBeingScanned.IsRootWeb)
                    {
                        fieldsToUpdate.Add("SiteSubWebs", webBeingScanned.Webs.Count);
                        fieldsToUpdate.Add("ParentSiteID", webBeingScanned.Site.ID.ToString().ToUpper());
                        fieldsToUpdate.Add("ParentWebID", webBeingScanned.ParentWebId.ToString().ToUpper());
                    }
                    else
                    {
                        fieldsToUpdate.Add("SiteSubWebs", siteBeingScanned.AllWebs.Count);
                    }
                    if (scanJobSettings.UseSiteLogo)
                    {
                        SPFieldUrlValue siteLogoURL = scanJobHelper.CreateURLFieldForSite(webBeingScanned, "LOGO", scanJobSettings);
                        if (!String.IsNullOrEmpty(siteLogoURL.Url))
                        {
                            fieldsToUpdate.Add("SiteImage", siteLogoURL);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                globalMethods.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
            return fieldsToUpdate;
        }
        public Decimal ConvertBytesToMegabytes(long bytes)
        { 
            return Math.Round(Decimal.Divide((Decimal)bytes, 1048576));
        }
        public Decimal GetPercentageOfQuotaUsed(SPSite site)
        {
            Decimal percentageOfQuotaUsed = 0;
            GlobalMethods globalMethods = new GlobalMethods();
            try
            {
                Decimal max = (Decimal)site.Quota.StorageMaximumLevel;
                Decimal used = (Decimal)site.Usage.Storage;
                if ((max != 0) && (used != 0))
                {
                    percentageOfQuotaUsed =  Math.Round(Decimal.Multiply((Decimal.Divide(used, max)), 100));
                }
            }
            catch (Exception ex)
            {
                globalMethods.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
            return percentageOfQuotaUsed;
        }
        public string GetLanguageNameFromLCID(uint lcid)
        {
            string languageName = "";
            GlobalMethods globalMethods = new GlobalMethods();
            try
            {
                foreach (SPLanguage l in SPRegionalSettings.GlobalInstalledLanguages)
                {
                    if (l.LCID == lcid)
                    {
                        languageName = l.DisplayName;
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                globalMethods.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
            return languageName;
        }
        public SPFieldUserValue GetUserValueAgainstSiteDirectory(SPWeb siteDirectoryWeb, SPUser user)
        {
            SPFieldUserValue uv = null;
            GlobalMethods globalMethods = new GlobalMethods();
            try
            {
                if (user != null)
                {
                    SPUser ensuredUser = siteDirectoryWeb.EnsureUser(user.LoginName); //ensure users against site directory web 
                    uv = new SPFieldUserValue(siteDirectoryWeb, ensuredUser.ID, ensuredUser.LoginName);
                }
            }
            catch (Exception ex)
            {
                globalMethods.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
            return uv;
        }
        public SPListItem GetOrCreateSiteListing(SPWeb siteDirectoryWeb, string webGUID)
        {
            SPListItem siteListing = null;
            GlobalMethods globalMethods = new GlobalMethods();
            try
            {
                SPList siteListingsList = siteDirectoryWeb.GetList(globalMethods.GetSiteListingsListURL(siteDirectoryWeb));
                SPQuery query = new SPQuery();
                query.Query = string.Concat("<Where><Eq><FieldRef Name='SiteID'/><Value Type='Text'>", webGUID, "</Value></Eq></Where>");
                SPListItemCollection siteListings = siteListingsList.GetItems(query);
                if (siteListings.Count == 1) //if there is a listimg, get the splistitem
                {
                    siteListing = siteListings[0];
                }
                if (siteListing == null) //if there is no a listing create one
                {
                    siteListing = siteListingsList.Items.Add();
                    siteListing.Update();
                }                
            }
            catch (Exception ex)
            {
                globalMethods.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
            return siteListing;
        }
        public string GetWebTemplateTitle(SPWeb rootWebInSite)
        {
            SPWebTemplateCollection templates = rootWebInSite.Site.GetWebTemplates((uint)SPRegionalSettings.GlobalServerLanguage.LCID);
            SPWebTemplate template = templates[string.Concat(rootWebInSite.WebTemplate, "#", rootWebInSite.Configuration.ToString())];
            return template.Title;
        }
        public SPFieldUserValueCollection GetSiteOwners(SPWeb siteDirectoryWeb, SPWebApplication webApplication, SPWeb rootWebInSite)
        {
            GlobalMethods globalMethods = new GlobalMethods();
            SPFieldUserValueCollection uvcOwners = new SPFieldUserValueCollection();
            try
            {
                ScanJobSettings scanJobSettings = webApplication.GetChild<ScanJobSettings>(webApplication.Id.ToString());
                IList<string> owners = new List<string>();
                if ((scanJobSettings.UseManageWebPermission) || (scanJobSettings.UseSiteOwnersGroup))
                {
                    foreach (SPUser u in rootWebInSite.AllUsers)
                    {
                        if (scanJobSettings.UseManageWebPermission)
                        {
                            if (rootWebInSite.DoesUserHavePermissions(SPBasePermissions.ManageWeb))
                            {
                                if (!owners.Contains(u.LoginName))
                                    owners.Add(u.LoginName);
                            }
                        }
                        if (scanJobSettings.UseSiteOwnersGroup)
                        {
                            foreach (SPGroup g in u.Groups)
                            {
                                if ((g.Name.Contains("Owners")) && (!owners.Contains(u.LoginName)))
                                {
                                    owners.Add(u.LoginName);
                                }
                            }
                        }
                    }
                }
                if (scanJobSettings.UserSiteCollectionAdministrators)
                {
                    foreach (SPUser uSCA in rootWebInSite.SiteAdministrators)
                        owners.Add(uSCA.LoginName);
                }
                foreach (string ownerAlias in owners)
                {
                    SPUser u = siteDirectoryWeb.EnsureUser(ownerAlias); //ensure users against site directory web 
                    uvcOwners.Add(new SPFieldUserValue(siteDirectoryWeb, u.ID, u.LoginName));
                }
            }
            catch (Exception ex)
            {
                globalMethods.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
            return uvcOwners;
        }
        public SPFieldUrlValue CreateURLFieldForSite(SPWeb webInSite, string SiteOrLogo, ScanJobSettings scanJobSettings)
        {
            GlobalMethods globalMethods = new GlobalMethods();
            SPFieldUrlValue urlField = new SPFieldUrlValue();
            try
            {
                switch (SiteOrLogo.ToUpper())
                {
                    case "SITE":
                        urlField.Description = webInSite.Title;
                        urlField.Url = webInSite.Url;
                        break;
                    case "LOGO":
                        if (scanJobSettings.EnsureSiteLogo) //get the nearest logo by enumerating parent sites until we find one and use default if nothing exists
                        {
                            Dictionary<string, string> siteLogo = GetNearestSiteLogo(webInSite, new Dictionary<string, string>(), scanJobSettings);
                            urlField.Description = siteLogo["Description"].ToString();
                            urlField.Url = siteLogo["Url"].ToString();
                        }
                        else //use whatever is set of the site for the logo
                        {
                            urlField.Description = webInSite.SiteLogoDescription;
                            urlField.Url = webInSite.SiteLogoUrl;
                        }
                        break;
                }
            }
            catch (Exception ex)
            {
                globalMethods.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
            return urlField;
        }
        public Dictionary<string, string> GetNearestSiteLogo(SPWeb webInSite, Dictionary<string, string> kvp, ScanJobSettings scanJobSettings)
        {
            if (string.IsNullOrEmpty(webInSite.SiteLogoUrl))
            {
                if (!webInSite.IsRootWeb)
                {
                    GetNearestSiteLogo(webInSite.ParentWeb, kvp, scanJobSettings);
                }
                else
                {
                    kvp.Add("Description", "");
                    kvp.Add("Url", scanJobSettings.DefaultLogoURL);
                }
            }
            else
            {
                kvp.Add("Description", webInSite.SiteLogoDescription);
                kvp.Add("Url", webInSite.SiteLogoUrl);
            }
            return kvp;
        }
        public Boolean IsSiteExcluded(SPWebApplication webApplication, string siteURL)
        {
            GlobalMethods globalMethods = new GlobalMethods();
            Boolean isSiteExcluded = false;
            try
            {
                ScanJobSettings scanJobSettings = webApplication.GetChild<ScanJobSettings>(webApplication.Id.ToString());
                if (!String.IsNullOrEmpty(scanJobSettings.ExclusionURLs))
                {
                    string[] exclusions = Regex.Split(scanJobSettings.ExclusionURLs, "\r\n");
                    foreach (string exclusion in exclusions)
                    {
                        string formattedExclusion = exclusion.Replace("%20", " ");
                        if (formattedExclusion == siteURL)
                        {
                            isSiteExcluded = true;
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                globalMethods.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
            return isSiteExcluded;
        }
        public void ProcessSiteListing(SPWeb siteDirectoryWeb, SPWeb webBeingScanned, SPWebApplication siteDirectoryWebApplication)
        {
            GlobalMethods globalMethods = new GlobalMethods();
            try
            {
                SPListItem siteListing = GetOrCreateSiteListing(siteDirectoryWeb, webBeingScanned.ID.ToString());
                SPList siteListingsList = siteDirectoryWeb.GetList(globalMethods.GetSiteListingsListURL(siteDirectoryWeb));
                if (!IsSiteExcluded(siteDirectoryWebApplication, webBeingScanned.Url)) //the site is not in the exclusion list so go ahead and update the list item with the latest metadata
                {
                    globalMethods.LockUpdateListItem(siteListingsList, siteListing.ID, GetSiteBeingScannedProperties(siteDirectoryWeb, webBeingScanned));
                }
                else //the site is in the exclusions list. if a listing exists, delete it as it has obviously been added after the exclusion was set
                {
                    globalMethods.DeleteSiteListingItem(siteListingsList, siteListing.ID);
                }
            }
            catch (Exception ex)
            {
                globalMethods.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
        }
    }
}
